home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / OS / FWThread / FWThrdGd.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  9.3 KB  |  307 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWThrdGd.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #ifndef FWTHRDGD_H
  11. #include "FWThrdGd.h"
  12. #endif
  13.  
  14. #ifndef FWPRIMEM_H
  15. #include "FWPriMem.h"
  16. #endif
  17.  
  18. #ifndef FWEXCDEF_H
  19. #include "FWExcDef.h"
  20. #endif
  21.  
  22. #ifdef FW_BUILD_MAC
  23. #pragma segment FWCommon
  24. #endif
  25.  
  26. //=====================================================================================
  27. // Class FW_CThreadSafe
  28. //=====================================================================================
  29.  
  30. FW_CThreadGuard *FW_CThreadSafe::fgSwitchGuards = 0;
  31. FW_CThreadGuard *FW_CThreadSafe::fgTerminationGuards = 0;
  32.  
  33.  
  34. //------------------------------------------------------------------------------
  35. // FW_CThreadSafe::NoteCreation
  36. //
  37. // Register the creation of a thread.  This should be called from a critical
  38. // section.  All guards are on the list of termination guards.
  39. //------------------------------------------------------------------------------
  40. void FW_CThreadSafe::NoteCreation(FW_ThreadID newlyCreatedThread)
  41. {
  42. #ifdef    FW_BUILD_MAC
  43.     FW_CThreadGuard *aThreadGuard;
  44.  
  45.     for (aThreadGuard = fgTerminationGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  46.     {
  47.         // A throw in the middle of this would be bad.  Catch everything and ignore
  48.         // it.  We can't do much else (except assert, and that might also be deadly).
  49.         FW_TRY
  50.         {
  51.             // The "Created" method can call AddThreadInfo to associate a chunk of storage 
  52.             // with this thread.
  53.             aThreadGuard->Created(newlyCreatedThread);
  54.         }
  55.         FW_CATCH_BEGIN
  56.         FW_CATCH_EVERYTHING()
  57.         {
  58.         }
  59.         FW_CATCH_END
  60.     }
  61. #endif
  62. }
  63.  
  64.  
  65. //------------------------------------------------------------------------------
  66. // FW_CThreadSafe::NoteTermination
  67. //
  68. // Register the destruction of a thread.  This should be called from a critical
  69. // section
  70. //------------------------------------------------------------------------------
  71. void FW_CThreadSafe::NoteTermination(FW_ThreadID threadBeingKilled)
  72. {
  73. #ifdef    FW_BUILD_MAC
  74.     FW_CThreadGuard *aThreadGuard;
  75.  
  76.     for (aThreadGuard = fgTerminationGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  77.     {
  78.         FW_TRY
  79.         {
  80.             // The "Terminating" method can call DeleteThreadInfo to remove the association 
  81.             // of any information with this thread.  
  82.             aThreadGuard->Terminating(threadBeingKilled);
  83.         }
  84.         FW_CATCH_BEGIN
  85.         FW_CATCH_EVERYTHING()
  86.         {
  87.         }
  88.         FW_CATCH_END
  89.     }
  90. #endif
  91. }
  92.  
  93.  
  94. #ifdef    FW_BUILD_MAC
  95. //------------------------------------------------------------------------------
  96. // FW_CThreadSafe::NoteSwitch
  97. //
  98. // Called between threads, indicating which are the old and the new threads.
  99. // This should be called from a critical section.
  100. //------------------------------------------------------------------------------
  101. void FW_CThreadSafe::NoteSwitch(FW_ThreadID aThread, FW_Boolean switchingIn)
  102. {
  103.     FW_CThreadGuard *aThreadGuard;
  104.     unsigned long mask;
  105.     
  106.     if (switchingIn)
  107.         mask = FW_CThreadGuard::kSwitchInThreadEvent;
  108.     else
  109.         mask = FW_CThreadGuard::kSwitchOutThreadEvent;
  110.  
  111.     for (aThreadGuard = fgSwitchGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  112.     {
  113.         // The "Switch()" method must not throw!  We cannot do an FW_TRY here 
  114.         // because in the case of interest (swapping exception globals), the
  115.         // Switch() would be entered with one set of exception globals and
  116.         // exit with another.  Don't ask how I discovered this...
  117.         if (aThreadGuard->GetMask() & mask)
  118.             aThreadGuard->Switch(aThread, switchingIn);
  119.     }
  120. }
  121. #endif
  122.  
  123.  
  124. //------------------------------------------------------------------------------
  125. // FW_CThreadSafe::RegisterTerminationGuard
  126. //
  127. // Add a ThreadGuard to the list of guardians
  128. //------------------------------------------------------------------------------
  129. void FW_CThreadSafe::RegisterTerminationGuard(FW_CThreadGuard *aThreadGuard)
  130. {
  131.     // Add this guardian to the head of the list
  132.     aThreadGuard->fNext = fgTerminationGuards;
  133.     fgTerminationGuards = aThreadGuard;
  134. }
  135.  
  136.  
  137. //------------------------------------------------------------------------------
  138. // FW_CThreadSafe::DeRegisterTerminationGuard
  139. //
  140. // Remove a ThreadGuard from the list of guardians
  141. //------------------------------------------------------------------------------
  142. void FW_CThreadSafe::DeRegisterTerminationGuard(FW_CThreadGuard *aThreadGuard)
  143. {
  144.     // Remove from the head of the list.  Should be safe as destructors are 
  145.     // executed in reverse order from the constructors
  146.     if (fgTerminationGuards == aThreadGuard)
  147.         fgTerminationGuards = aThreadGuard->fNext;
  148. }
  149.  
  150.  
  151. //------------------------------------------------------------------------------
  152. // FW_CThreadSafe::RegisterSwitchGuard
  153. //
  154. // Add a ThreadGuard to the list of guardians
  155. //------------------------------------------------------------------------------
  156. void FW_CThreadSafe::RegisterSwitchGuard(FW_CThreadGuard *aThreadGuard)
  157. {
  158.     // Add this guardian to the head of the list
  159.     aThreadGuard->fNext = fgSwitchGuards;
  160.     fgSwitchGuards = aThreadGuard;
  161. }
  162.  
  163.  
  164. //------------------------------------------------------------------------------
  165. // FW_CThreadSafe::DeRegisterSwitchGuard
  166. //
  167. // Remove a ThreadGuard from the list of guardians
  168. //------------------------------------------------------------------------------
  169. void FW_CThreadSafe::DeRegisterSwitchGuard(FW_CThreadGuard *aThreadGuard)
  170. {
  171.     // Remove from the head of the list.  Should be safe as destructors are 
  172.     // executed in reverse order from the constructors
  173.     if (fgSwitchGuards == aThreadGuard)
  174.         fgSwitchGuards = aThreadGuard->fNext;
  175. }
  176.  
  177.  
  178. //=====================================================================================
  179. // Class FW_CThreadGuard
  180. //=====================================================================================
  181.  
  182. //------------------------------------------------------------------------------
  183. // FW_CThreadGuard::FW_CThreadGuard
  184. //
  185. // Constructor for FW_CThreadGuard
  186. //------------------------------------------------------------------------------
  187. FW_CThreadGuard::FW_CThreadGuard(unsigned long threadEventMask) :
  188.     fActiveThreads(0),
  189.     fMask(threadEventMask)
  190. {
  191.     // Always check for termination if checking for anything
  192.     if (threadEventMask != 0)
  193.         FW_CThreadSafe::RegisterTerminationGuard(this);
  194.  
  195.     if (threadEventMask & (kSwitchInThreadEvent | kSwitchOutThreadEvent))
  196.         FW_CThreadSafe::RegisterSwitchGuard(this);
  197. }
  198.  
  199.  
  200. //------------------------------------------------------------------------------
  201. // FW_CThreadGuard::~FW_CThreadGuard
  202. //
  203. // Destructor for FW_CThreadGuard
  204. //------------------------------------------------------------------------------
  205. FW_CThreadGuard::~FW_CThreadGuard()
  206. {
  207.     FW_CThreadSafe::DeRegisterTerminationGuard(this);
  208.     FW_CThreadSafe::DeRegisterSwitchGuard(this);
  209.  
  210.     while (fActiveThreads != 0)
  211.     {
  212.         FW_SThreadItem *anItem = fActiveThreads;
  213.  
  214.         fActiveThreads = anItem->fNext;
  215.         FW_PrimitiveFreeBlock(anItem);
  216.     }
  217. }
  218.  
  219.  
  220. #ifdef    FW_BUILD_MAC
  221. //------------------------------------------------------------------------------
  222. // FW_CThreadGuard::Switch
  223. //
  224. // Called between thread switches
  225. //------------------------------------------------------------------------------
  226. void FW_CThreadGuard::Switch(FW_ThreadID, FW_Boolean)
  227. {
  228.     // Default is to do nothing
  229. }
  230. #endif
  231.  
  232.  
  233. //------------------------------------------------------------------------------
  234. // FW_CThreadGuard::AddThreadInfo
  235. //
  236. // Associates a void* with a ThreadID.  
  237. //------------------------------------------------------------------------------
  238. void FW_CThreadGuard::AddThreadInfo(FW_ThreadID aThreadID, void *threadInfo)
  239. {
  240.     FW_SThreadItem *newItem = (FW_SThreadItem *)FW_PrimitiveAllocateBlock(sizeof(FW_SThreadItem));
  241.  
  242.     // [jkp] -- what's the approved method of suicide?
  243.     if (newItem != 0)
  244.     {
  245.         newItem->fThreadID = aThreadID;
  246.         newItem->fThreadInfo = threadInfo;
  247.  
  248.         newItem->fNext = fActiveThreads;
  249.         fActiveThreads = newItem;
  250.     }
  251. }
  252.  
  253.  
  254. //------------------------------------------------------------------------------
  255. // FW_CThreadGuard::GetThreadInfo
  256. //
  257. // Returns the void* with a ThreadID.  
  258. //------------------------------------------------------------------------------
  259.  
  260. void *FW_CThreadGuard::GetThreadInfo(FW_ThreadID aThreadID)
  261. {
  262.     for (FW_SThreadItem *anItem = fActiveThreads; anItem != 0; anItem = anItem->fNext)
  263.     {
  264.         if (anItem->fThreadID == aThreadID)
  265.             return anItem->fThreadInfo;
  266.     }
  267.  
  268.     // [jkp] -- what's the approved method of suicide?
  269.     return 0;
  270. }
  271.  
  272.  
  273. //------------------------------------------------------------------------------
  274. // FW_CThreadGuard::RemoveThreadInfo
  275. //
  276. // Removes the association between a ThreadID and any chunk of data it pointed
  277. // to.  The caller must destroy the chunk of data, we don't know how.
  278. //------------------------------------------------------------------------------
  279. void FW_CThreadGuard::RemoveThreadInfo(FW_ThreadID aThreadID)
  280. {
  281.     FW_SThreadItem **itemPtr = &fActiveThreads;
  282.     FW_SThreadItem *anItem = fActiveThreads;
  283.  
  284.     while (anItem != 0)
  285.     {
  286.         if (anItem->fThreadID == aThreadID)
  287.         {
  288.             *itemPtr = anItem->fNext;
  289.             FW_PrimitiveFreeBlock(anItem);
  290.             return;
  291.         }
  292.         itemPtr = &anItem->fNext;
  293.         anItem = anItem->fNext;
  294.     }
  295.     // [jkp] -- what's the approved method of suicide?
  296. }
  297.  
  298.  
  299. //------------------------------------------------------------------------------
  300. // FW_CThreadGuard::GetMask
  301. //------------------------------------------------------------------------------
  302. unsigned long FW_CThreadGuard::GetMask() const
  303. {
  304.     return fMask;
  305. }
  306.  
  307.